﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Windows.Input;
using DG.Common.EF.WPF;
using DG.Common.Patterns.Commands;
using DG.Common.Patterns.MVVM;
using TCC.ControleFluxoDeCaixa.Apresentacao.Views;
using TCC.ControleFluxoDeCaixa.Model.Contas;
using TCC.ControleFluxoDeCaixa.Model.Entities;
using TCC.ControleFluxoDeCaixa.Model.Fluxo;

namespace TCC.ControleFluxoDeCaixa.Apresentacao.ViewModels
{
    public class LancamentoRecorrentCadastroWindowViewModel : EntityCRUDViewModelBase<FluxoDeCaixaContextFiltrado, LancamentoRecorrente>
    {
        private ObservableCollection<LancamentoRecorrenteUnidadeTempo> _periodicidade;
        private ObservableCollection<LancamentoRecorrenteVencimento> _vencimentos;
        private LancamentoRecorrenteVencimento _selectedVencimento;

        public IEnumerable<Categoria> ListaCategorias
        {
            get
            {
                return Context.Categorias.ToArray();
            }
        }
        public IEnumerable<ContaFinanceira> ListaContas
        {
            get
            {
                return Context.ContaFinanceiras.ToArray();
            }
        }
        public IEnumerable<object> ListaUnidades
        {
            get
            {
                return Enum.GetValues(typeof (UnidadeTempo)).Cast<object>().ToArray();
            }
        }
        public IList<LancamentoRecorrenteVencimento> ListaVencimentos
        {
            get
            {
                return _vencimentos;
            }
        }

        public LancamentoRecorrenteVencimento SelectedVencimento
        {
            get { return _selectedVencimento; }
            set { _selectedVencimento = value; OnPropertyChanged("SelectedVencimento"); }
        }

        public ObservableCollection<LancamentoRecorrenteUnidadeTempo> Periodicidade
        {
            get { return _periodicidade; }
        }

        protected override void BeforeSave()
        {
            AtualizarPerioidicidade();
        }

        private void AtualizarPerioidicidade()
        {
            foreach (var tempo in Entity.UnidadesDeRecorrencia.Where(m => !Periodicidade.Contains(m)).ToArray())
            {
                Entity.UnidadesDeRecorrencia.Remove(tempo);
            }
            foreach (var tempo in Periodicidade.Where(m => !Entity.UnidadesDeRecorrencia.Contains(m)).ToArray())
            {
                tempo.LancamentoRecorrente = Entity;
                Entity.UnidadesDeRecorrencia.Add(tempo);
            }
        }

        protected override void AfterSetAction()
        {
            _periodicidade = new ObservableCollection<LancamentoRecorrenteUnidadeTempo>(Entity.UnidadesDeRecorrencia.ToArray());
            _vencimentos = new ObservableCollection<LancamentoRecorrenteVencimento>(Entity.Lancamentos.ToArray());

            
            OnPropertyChanged("Periodicidade");
        }

        public ICommand AtualizarVencimentosCommand
        {
            get
            {
                return new FunctionalCommand(() =>
                {
                    AtualizarPerioidicidade();
                    Entity.AtualizarListaDeVencimentos();
                    foreach (var vencimento in Entity.Lancamentos.Where(v => !ListaVencimentos.Contains(v)).ToArray())
                    {
                        ListaVencimentos.Add(vencimento);
                    }
                    foreach (var vencimento in ListaVencimentos.Where(v => !Entity.Lancamentos.Contains(v)).ToArray())
                    {
                        ListaVencimentos.Remove(vencimento);
                    }
                });
            }
        }

        public object DeletarUnidadeCommand
        {
            get
            {
                return new FunctionalCommand((arg) =>
                {
                    var mov = arg as LancamentoRecorrenteUnidadeTempo;
                    Periodicidade.Remove(mov);
                });
            }
        }
        public ICommand AdicionarUnidadeCommand
        {
            get
            {
                return new FunctionalCommand(() =>
                {
                    Periodicidade.Add(new LancamentoRecorrenteUnidadeTempo {LancamentoRecorrente = Entity});
                    OnPropertyChanged("Periodicidade");
                });
            }
        }

        public ICommand VincularCommand
        {
            get
            {
                return new FunctionalCommand((arg) =>
                {
                    var venc = (LancamentoRecorrenteVencimento)arg;
                    var entity = EntityListViewerWindow.Escolher<Lancamento>(()=> Context);
                    if (entity != null) venc.Lancamento = Context.Lancamentos.Find(Context.Metadata.GetKeysFor(entity));

                }, arg => arg is LancamentoRecorrenteVencimento);
            }
        }

        public LancamentoRecorrentCadastroWindowViewModel()
        {
            Validator.AddMethodValidator(() => Periodicidade.GroupBy(c => c.UnidadeTempo).All(g=> g.Count() == 1),
                errorMessage: () => "Unidade de Tempo Duplicada");
        }
    }
}